/* ----------------------------------------------------------------------
*
* Copyright (C) 2025 XiaoFei. All rights reserved.
*
* @file:		XiaoFei_CRC.c
* @author:		XiaoFei
* @Date:     	09-August-2025
* @Revision: 	V1
* @Project: 	XiaoFei BSP Library
*
* -------------------------------------------------------------------- */

#include "stm32f10x.h"
#include "XiaoFei_CRC.h"

/* 
* @function: 	CRC_Get
* @parameter:	[in] Buffer				    The first address of the data that will be computed.
* @parameter:	[in] Length				    The length of the data that will be computed.
* @parameter:	[in] isReset				Write 0x00 if you want to reset the CRC calculation before calculating.
* @return:		The result of the CRC operation.
*/
unsigned int CRC_Get(unsigned int* Buffer, unsigned int Length, unsigned char isReset)
{
	CRC_Rcc(1);
	if(isReset != 0x00)
		CRC_ResetDR();
	return CRC_CalcBlockCRC(Buffer,Length);
}

/* 
* @function: 	My_Inv8
* @parameter:	[in] data				    The original data that will be used as a bit inversion operation.
* @return:		Calculation results after bit inversion.
*/
unsigned char My_Inv8(unsigned char data)
{
	unsigned char temp = 0x00;
	for(unsigned char i=0;i<8;i++)
		if(data&(1<<i))
			temp |= 1<<(7-i);
	return temp;
}

/* 
* @function: 	My_Inv16
* @parameter:	[in] data				    The original data that will be used as a bit inversion operation.
* @return:		Calculation results after bit inversion.
*/
unsigned short int My_Inv16(unsigned short int data)
{
	unsigned short int temp = 0x0000;
	for(unsigned char i=0;i<16;i++)
		if(data&(1<<i))
			temp |= 1<<(15-i);
	return temp;
}

/* 
* @function: 	My_Inv32
* @parameter:	[in] data				    The original data that will be used as a bit inversion operation.
* @return:		Calculation results after bit inversion.
*/
unsigned int My_Inv32(unsigned int data)
{
	unsigned int temp = 0x00000000;
	for(unsigned char i=0;i<32;i++)
		if(data&(1<<i))
			temp |= 1<<(31-i);
	return temp;
}

/* 
* @function: 	My_CRC32
* @parameter:	[in] data				    The first address of the data that will be computed.
* @parameter:	[in] Length				    The length of the data that will be computed.
* @parameter:	[in] CRC32				    Detailed parameters for the CRC32 operation you need.
* @parameter:	[in] isReset				Write 0x00 if you want to reset the CRC calculation before calculating.
* @return:		The result of the CRC32 operation.
*/
unsigned int My_CRC32(unsigned char* data, unsigned int Length, CRC32_Typedef* CRC32, unsigned char isReset)
{
	unsigned char Data;
	if(isReset != 0x00)
		CRC32->temp = CRC32->init;
	while(Length--)
	{
		Data = CRC32->invin ? My_Inv8(*data) : (*data);
		CRC32->temp = CRC32->temp^(Data<<24);
		for(unsigned int i=0; i<8; i++)
			if(CRC32->temp&0x80000000)
				CRC32->temp = (CRC32->temp<<1)^CRC32->ploy;
			else
				CRC32->temp = CRC32->temp<<1;
		data++;
	}
	return CRC32->invout ? My_Inv32(CRC32->temp) : CRC32->temp;
}

/* 
* @function: 	My_CRC16
* @parameter:	[in] data				    The first address of the data that will be computed.
* @parameter:	[in] Length				    The length of the data that will be computed.
* @parameter:	[in] CRC16				    Detailed parameters for the CRC16 operation you need.
* @parameter:	[in] isReset				Write 0x00 if you want to reset the CRC calculation before calculating.
* @return:		The result of the CRC16 operation.
*/
unsigned short int My_CRC16(unsigned char* data, unsigned int Length, CRC16_Typedef* CRC16, unsigned char isReset)
{
	unsigned char Data;
	if(isReset != 0x00)
		CRC16->temp = CRC16->init;
	while(Length--)
	{
		Data = CRC16->invin ? My_Inv8(*data) : (*data);
		CRC16->temp = CRC16->temp^(Data<<8);
		for(unsigned int i=0; i<8; i++)
			if(CRC16->temp&0x8000)
				CRC16->temp = (CRC16->temp<<1)^CRC16->ploy;
			else
				CRC16->temp = CRC16->temp<<1;
		data++;
	}
	return CRC16->invout ? My_Inv16(CRC16->temp) : CRC16->temp;
}

/* 
* @function: 	My_CRC8
* @parameter:	[in] data				    The first address of the data that will be computed.
* @parameter:	[in] Length				    The length of the data that will be computed.
* @parameter:	[in] CRC8				    Detailed parameters for the CRC8 operation you need.
* @parameter:	[in] isReset				Write 0x00 if you want to reset the CRC calculation before calculating.
* @return:		The result of the CRC8 operation.
*/
unsigned char My_CRC8(unsigned char* data, unsigned int Length, CRC8_Typedef* CRC8, unsigned char isReset)
{
	unsigned char Data;
	if(isReset != 0x00)
		CRC8->temp = CRC8->init;
	while(Length--)
	{
		Data = CRC8->invin ? My_Inv8(*data) : (*data);
		CRC8->temp = CRC8->temp^Data;
		for(unsigned int i=0; i<8; i++)
			if(CRC8->temp&0x80)
				CRC8->temp = (CRC8->temp<<1)^CRC8->ploy;
			else
				CRC8->temp = CRC8->temp<<1;
		data++;
	}
	return CRC8->invout ? My_Inv8(CRC8->temp) : CRC8->temp;
}

